package indi.kider.server.bill.service;

import indi.kider.common.constant.BillTypeCons;
import indi.kider.common.constant.ReadingAddMethodCons;
import indi.kider.common.constant.ReadingTypeCons;
import indi.kider.common.constant.StatusCons;
import indi.kider.common.model.bill.BalanceTask;
import indi.kider.common.model.bill.Meter;
import indi.kider.common.model.bill.MeterReadingQuery;
import indi.kider.common.model.bill.Reading;
import indi.kider.common.model.meter.InstantCommand;
import indi.kider.common.model.meter.MeterReading;
import indi.kider.server.bill.mapper.ReadingMapper;
import indi.kider.server.bill.service.related.MeterClientService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import pers.vankid.common.constant.HttpCode;
import pers.vankid.common.model.base.CommonResponse;
import pers.vankid.common.utils.jdk.ListUtil;
import pers.vankid.common.utils.page.PageRequest;
import pers.vankid.common.utils.page.PageResponse;
import pers.vankid.common.utils.page.PageUtil;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by shixj on 2018/5/4.
 */
@Service
@Slf4j
public class ReadingServiceImpl implements ReadingService {

    @Autowired
    private ReadingMapper readingMapper;
    @Autowired
    private BalanceTaskService balanceTaskService;
    @Autowired
    private MeterClientService meterClientService;
    @Autowired
    private MeterService meterService;

    /**
     * 人工抄表
     * （需指定归属）
     * 更新任务水电读数
     *
     * @param meterReadingQuery
     * @return
     */
    @Override
    @Transactional
    public MeterReading mannalRead(MeterReadingQuery meterReadingQuery) throws Exception {
        InstantCommand command = new InstantCommand();
        MeterReading clientReading;
        Meter query = new Meter();
        query.setHousesId(meterReadingQuery.getHousesId());
        query.setMeterType(meterReadingQuery.getMeterType());
        Meter meter = meterService.selectOne(query);
        if (meter == null) throw new Exception("房屋未安装该类表具！");
        command.setCld(meter.getLocationParam());
        command.setZddz(meter.getConcentrator());
        if (meterReadingQuery.getMeterType().equals(BillTypeCons.WATER)) {
            command.setGn("cb");
            command.setNr("1F188");
            CommonResponse waterResopnse = meterClientService.readWaterMeter(command);
            if (waterResopnse.getStatus().equals(HttpCode.SUCCESS_GET)) {
                clientReading = (MeterReading) waterResopnse.getData();
            } else throw new Exception(waterResopnse.getMsg());
        } else {
            command.setGn("cb");
            command.setNr("1F129");
            CommonResponse waterResopnse = meterClientService.readPowerMeter(command);
            if (waterResopnse.getStatus().equals(HttpCode.SUCCESS_GET)) {
                clientReading = (MeterReading) waterResopnse.getData();
            } else throw new Exception(waterResopnse.getMsg());
        }
        if (meterReadingQuery.getRentId() != null && meterReadingQuery.getRentId() > 0) {
            saveReadingByClient(clientReading, meterReadingQuery.getRentId());
        }
        return clientReading;
    }

    /**
     * 根据抄表读数 保存读数记录并更新任务
     *
     * @param clientReading
     * @param rentId
     */
    @Override
    @Transactional
    public void saveReadingByClient(MeterReading clientReading, Long rentId) {
        Reading reading = saveReadingByMeterReading(clientReading, rentId);
        //更新任务
        updateTaskReading(reading);
    }

    /**
     * 根据抄表数据记录读数
     *
     * @param meterReading
     * @param rentId
     * @return
     */
    private Reading saveReadingByMeterReading(MeterReading meterReading, Long rentId) {
        Reading reading = new Reading();
        reading.setBillAttribution(rentId);
        reading.setType(meterReading.getType());
        reading.setReading(meterReading.getUsedValue().floatValue());
        reading.setMethod(ReadingAddMethodCons.MANUAL);
        reading.setTime(meterReading.getDataDate());
        readingMapper.insert(reading);
        return reading;
    }

    /**
     * 设置读数时间
     *
     * @param reading
     */
    private void setTime(Reading reading) {
        if (reading != null && reading.getTime() == null)
            reading.setTime(new Date());
    }

    /**
     * 水电入库(自动入库)
     *
     * @param reading
     * @return
     */
    @Override
    @Transactional
    public Reading add(Reading reading) {
        reading.setMethod(ReadingAddMethodCons.AUTO);
        setTime(reading);
        reading.setBillAttribution(getMeterMatchedAttribution(reading));
        readingMapper.insert(reading);
        return reading;
    }

    /**
     * 批量入库
     * 水电入库(自动入库)
     *
     * @param readings
     * @return
     */
    @Override
    @Transactional
    public void batchAdd(List<Reading> readings) {
        readings.stream().forEach(reading -> setTime(reading));
        List<List<Reading>> list = ListUtil.split(readings, new ArrayList<>());
        if (list != null) {
            list.stream().forEach(tempList -> readingMapper.batchInsert(tempList));
        }
        new Thread("匹配读数归属" + new Date()) {
            @Override
            public void run() {
                matchAttribution(readings);
            }
        }.start();
    }

    /**
     * 更新任务水电读数
     *
     * @param reading
     */

    private BalanceTask updateTaskReading(Reading reading) {
        BalanceTask query = new BalanceTask();
        query.setBillAttribution(reading.getBillAttribution());
        query.setStatus(StatusCons.VALID);//允许重复抄读
        query.setType(reading.getType());//1水2电
        BalanceTask balanceTask = balanceTaskService.queryOne(query);
        balanceTask.setReading(reading.getReading());
        balanceTask.setReadingId(reading.getId());
        balanceTask.setReadingTime(reading.getTime());
        balanceTaskService.update(balanceTask);
        return balanceTask;
    }

    /**
     * 根据表号和时间更新r_reading表的归属ID
     */
    private void matchAttribution(List<Reading> readings) {
        readings.stream().forEach(reading -> {
            reading.setBillAttribution(getMeterMatchedAttribution(reading));
            readingMapper.updateByPrimaryKeySelective(reading);
            updateTaskReading(reading);
        });
    }

    /**
     * 根据表号获取归属
     *
     * @param reading
     * @return
     */
    private Long getMeterMatchedAttribution(Reading reading) {
        Long attribution = 0L;
        if (reading.getType().equals(ReadingTypeCons.WATER))
            attribution = readingMapper.getWaterMeterMatchedAttribution(reading);
        else if (reading.getType().equals(ReadingTypeCons.POWER))
            attribution = readingMapper.getPowerMeterMatchedAttribution(reading);
        return attribution;
    }

    /**
     * 查询读数流水信息
     *
     * @param request
     * @return
     */
    @Override
    public PageResponse<Reading> query(PageRequest<Reading> request) {
        Reading query = request.getQuery();
        PageUtil.start(request);
        return PageUtil.getPageResponse(readingMapper.select(query));
    }

    @Override
    public Reading queryById(Long id) {
        return readingMapper.selectByPrimaryKey(id);
    }
}
